" 太多内容了.....
" 别钻牛角尖

if exists('g:autoloaded_scriptV')
    finish
en
let g:autoloaded_scriptV = 1


"\ Utility
    func! s:function(name) abort
        return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '.*\zs<SNR>\d\+_'),''))
    endf

    func! s:subs(str,pat,rep) abort
        return substitute(
                    \ a:str,
                    \ '\v\C' . a:pat,
                    \ a:rep,
                    \ '',
                   \ )
    endf

    func! s:subs_g(str,pat,rep) abort
        return substitute(
                    \ a:str,
                    \ '\v\C' . a:pat,
                    \ a:rep,
                    \ 'g',
                  \ )
    endf

    func! s:shellesc(arg) abort
        if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
            return a:arg
        elseif &shell =~# 'cmd' && a:arg !~# '"'
            return '"'.a:arg.'"'
        el
            return shellescape(a:arg)
        en
    endf

    func! s:fnameescape(file) abort
        if exists('*fnameescape')
            return fnameescape(a:file)
        el
            return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
        en
    endf

    func! s:shellslash(path) abort
        if exists('+shellslash') && !&shellslash
            return s:subs_g(a:path,'\\','/')
        el
            return a:path
        en
    endf

    func! s:fcall(fn, path, ...) abort
        let ns = matchstr(a:path, '^\a\a\+\ze:')
        "\ echom "ns 是: "   ns
        if len(ns)
        \&& exists('*' . ns . '#' . a:fn)
            return call(
                  \ ns . '#' . a:fn,
                  \ [a:path] + a:000,
               \ )
                    "\ 形如coc#func1
        el
            return call(
                  \ a:fn,
                  \ [a:path] + a:000,
                \ )
        en
    endf

    func! s:glob(pattern) abort
        return s:fcall('glob', a:pattern, 0, 1)
    endf

    func! s:globrtp(my_expr) abort
          " 在&runtimepath中查找文件
        return globpath(
                  \ escape(&runtimepath, ' ') ,
                  \ a:my_expr                    ,
                  \ 1                         ,
               \ )
    endf

    func! s:isdirectory(path) abort
        return s:fcall('isdirectory', a:path)
    endf

    func! s:file_readable(path) abort
        return s:fcall('filereadable', a:path)
    endf

    func! s:read_file(path, ...) abort
        if a:0
            return s:fcall('readfile', a:path, '', a:1)
                    "\ readfile(fname , type , max)
                                     "\ type为空
                    "\ 下面有call s:read_file(file, 500)
                                          "\ 最多读500行, 这是要应对文件头全是注释的情况?

        el
            return s:fcall('readfile', a:path)
        en
    endf

"\ Completion
    func! scriptV#complete(A,L,P) abort
        let sep = !exists("+shellslash") || &shellslash ? '/' : '\'
        let cheats = {
                    \ 'a': 'autoload',
                    \ 'd': 'doc',
                    \ 'f': 'ftplugin',
                    \ 'i': 'indent',
                    \ 'p': 'plugin',
                    \ 's': 'syntax'}
        if a:A =~# '^\w[\\/]' && has_key(cheats,a:A[0])
            let request = cheats[a:A[0]].a:A[1:-1]
        el
            let request = a:A
        en
        let pattern = substitute(request,'/\|\'.sep,'*'.sep,'g').'*'
        let found = {}
        for glob in split(&runtimepath, ',')
            for path in map(s:glob(glob), 'fnamemodify(v:val, ":p")')
                let matches = s:glob(path.sep.pattern)
                call map(matches,'s:isdirectory(v:val) ? v:val.sep : v:val')
                call map(matches,'fnamemodify(v:val, ":p")[strlen(path)+1:-1]')
                for match in matches
                    let found[match] = 1
                endfor
            endfor
        endfor
        return sort(keys(found))
    endf

"\ :PP, :PPmsg
    let s:escapes = {
                \ "\b": '\b',
                \ "\e": '\e',
                \ "\f": '\f',
                \ "\n": '\n',
                \ "\r": '\r',
                \ "\t": '\t',
                \ "\"": '\"',
                \ "\\": '\\'}

    func! scriptV#dump(object, ...) abort
        let opt = extend({'width': 0, 'level': 0, 'indent': 1, 'tail': 0, 'seen': []}, a:0 ? copy(a:1) : {})
        let opt.seen = copy(opt.seen)
        let childopt = copy(opt)
        let childopt.tail += 1
        let childopt.level += 1
        for i in range(len(opt.seen))
            if a:object is opt.seen[i]
                return type(a:object) == type([]) ? '[...]' : '{...}'
            en
        endfor
        if type(a:object) ==# type('')
            if a:object =~# "[\001-\037\177']"
                let dump = '"'.s:subs_g(a:object, "[\001-\037\177\"\\\\]", '\=get(s:escapes, submatch(0), printf("\\%03o", char2nr(submatch(0))))').'"'
            el
                let dump = string(a:object)
            en
        elseif type(a:object) ==# type([])
            let childopt.seen += [a:object]
            let dump = '['.join(map(copy(a:object), 'scriptV#dump(v:val, {"seen": childopt.seen, "level": childopt.level})'), ', ').']'
            if opt.width && opt.level + len(s:subs_g(dump, '.', '.')) > opt.width
                let space = repeat(' ', opt.level)
                let dump = "[".join(map(copy(a:object), 'scriptV#dump(v:val, childopt)'), ",\n ".space).']'
            en
        elseif type(a:object) ==# type({})
            let childopt.seen += [a:object]
            let keys = keys(a:object)
            if type(keys) != type([])
                return "test_null_dict()"
            en
            call sort(keys)
            let dump = '{'.join(map(copy(keys), 'scriptV#dump(v:val) . ": " . scriptV#dump(a:object[v:val], {"seen": childopt.seen, "level": childopt.level})'), ', ').'}'
            if opt.width && opt.level + len(s:subs_g(dump, '.', '.')) > opt.width
                let space = repeat(' ', opt.level)
                let lines = []
                let last = get(keys, -1, '')
                for k in keys
                    let prefix = scriptV#dump(k) . ':'
                    let suffix = scriptV#dump(a:object[k]) . ','
                    if len(space . prefix . ' ' . suffix) >= opt.width - (k ==# last ? opt.tail : '')
                        call extend(lines, [prefix, scriptV#dump(a:object[k], childopt) . ','])
                    el
                        call extend(lines, [prefix . ' ' . suffix])
                    en
                endfor
                let dump = s:subs("{".join(lines, "\n " . space), ',$', '}')
            en
        elseif type(a:object) ==# type(function('tr'))
            let dump = s:subs(s:subs(string(a:object), '^function\(''(\d+)''', 'function(''{\1}'''), ',.*\)$', ')')
        el
            let dump = string(a:object)
        en
        return dump
    endf

    func! s:backslashdump(value, indent) abort
            let out = scriptV#dump(a:value, {'level': 0, 'width': &textwidth - &shiftwidth * 3 - a:indent})
            return s:subs_g(out, '\n', "\n".repeat(' ', a:indent + &shiftwidth * 3).'\\')
    endf

    func! scriptV#pp_command(bang, lnum, value) abort
        if v:errmsg !=# '' && a:value is# 0
            return
        elseif a:lnum == -1
            echo scriptV#dump(a:value, {'width': a:bang ? 0 : &columns-1})
        el
            exe a:lnum
            let indent = indent(prevnonblank('.'))
            if a:bang
                let out = scriptV#dump(a:value)
            el
                let out = s:backslashdump(a:value, indent)
            en
            put =repeat(' ', indent).'PP '.out
            '[
        en
    endf

    func! scriptV#ppmsg_command(bang, count, value) abort
        if v:errmsg !=# ''
            return
        elseif &verbose >= a:count
            for line in split(scriptV#dump(a:value, {'width': a:bang ? 0 : &columns-1}), "\n")
                echomsg line
            endfor
        en
    endf

" g!
"\ g=
    func! s:opFunc(txt) abort
        silent exe
                    \ 'norm! `['
                    \ . get(
                          \ {'l': 'V',  'b': "\<C-V>"},
                          \ a:txt[0],
                          \ 'v',
                         \ )
                    \ . '`]y'
                      "\ 默认是用v进入visual mode, 如果是linewise, 就用V进入行模式, b表示blockwise
        redraw
        return @@
    endf

    func! scriptV#filterop(...) abort
        if !a:0
            set operatorfunc=scriptV#filterop
            return 'g@'
        en
        let backups = [&selection, &clipboard, @@]
        try
            set selection=inclusive
            set clipboard=

            let my_expr = s:opFunc(a:1)
            echom "my_expr 是: "   my_expr
            let @@ =   matchstr(my_expr, '^\_s\+')
               \ . scriptV#dump( eval( s:subs_g(my_expr , '\n%(\s*\\)='  ,  '') ) )
               \ . matchstr(my_expr, '\_s\+$')

            if @@ !~# '^\n*$'
                norm! gvp
                "\ 1 + 3 * 2
            en

        catch /^.*/
            echohl ErrorMSG
            echo v:errmsg
            echohl NONE
        finally
            let [&selection, &clipboard, @@] = backups
        endtry
    endf

" :Verbose
    func! scriptV#verbose_command(level, ex_cmd) abort
        let temp = tempname() . '.vim'
        let ver_file = &verbosefile
        "\ ✗不加这函数, 文件可能不存在✗
        "\ call writefile(
        "\           \[':' . a:level . 'Verbose  ' . a:ex_cmd ],
        "\           \temp,
        "\           \'',
        "\       \  )
        "\         "\ \)
        "\         " 'b':   binary, (no NL used)

        return     'try|' .
            \     'let &verbosefile = ' . string(temp) . '|' .
            \     'silent ' . a:level . 'verbose exe ' . string(a:ex_cmd) . '|' .
            \ 'finally|' .
                \ 'let &verbosefile = ' . string(ver_file) . '|' .
            \ 'endtry|' .
            \ 'pedit ' . temp . '| silent! wincmd P | setl buftype=nofile'
            "\ \ 'split ' . temp
                          "\ 加这个silent是因为:
                            if search('No mapping found')
                                silent! bdelete
                                echo '键位可用'
                            en

        "\ 这会报错, 别加string
        "\ let &verbosefile = string(ver_file)

        " todo: 放进quickfix
    endf

" :Scriptnames
    func! scriptV#capture(ex_cmd) abort
        try
            redir => out
            exe 'silent! '.a:ex_cmd
        finally
            redir END
        endtry
        return out
    endf

    func! scriptV#scriptnames_qflist() abort
        let names = scriptV#capture('scriptnames')
        let virtual = get(g:, 'virtual_scriptnames', {})
                          " virtual_scriptnames为空, 没有任何说明,出现了3处左右
                          " 用于覆盖filename?
        let list = []
        for line in split(names, "\n")
            if line =~# ':'
                let filename = expand(matchstr(line, ': \zs.*'))
                call add(
                        \ list,
                        \ {
                            \ 'text': matchstr(line, '\d\+'),
                            \ 'filename': get(virtual, filename, filename),
                            \ 'lnum': 1,
                         \ },
                     \ )
            en
        endfor
        return list
    endf

    func! scriptV#scriptname(file) abort
        if a:file =~# '\v^\d+$'
            return get(scriptV#scriptnames_qflist(), a:file-1, {'filename': a:file}).filename
        el
            return a:file
        en
    endf

    func! scriptV#scriptid(file_name) abort
        let file_name = fnamemodify(expand(a:file_name), ':p')
        for script in scriptV#scriptnames_qflist()
            if script.filename ==# file_name
                return +script.text
            en
        endfor
        return 0
    endf

    func! scriptV#prepare_eval(string, ...) abort
        if a:string =~? '<sid>'
            let sid = scriptV#scriptid(@%)
            if sid
                return substitute(a:string, '\c<sid>', '<SNR>' . sid . '_', 'g')
            en
        en
        return a:string
    endf

" :Messages
    " to do
    " 过滤掉这些:
        " 956L, 35232B written
    func! scriptV#messages_command(bang, count, arg) abort
        let command = (a:count > -1 ? a:count : '') . 'messages'
        " let command = (a:count > -1 ? a:count : '') . 'echo v:errmsg'
        if !empty(a:arg)
            return command . ' ' . a:arg
        en
        let lines = []
        let virtual = get(g:, 'virtual_scriptnames', {})
        for line in split(
                        \ scriptV#capture(command),
                        \ '\n\+',
                       \ )
            let lnum = matchstr(
                            \ line,
                            \ '\C^line\s\+\zs\d\+\ze:$',
                           \ )
            if lnum && len(lines) && lines[-1].text =~# ':$'
                let lines[-1].text = substitute(lines[-1].text, ':$', '[' . lnum . ']:', '')
            el
                call add(lines, {'text': line})
            en

            let functions = matchstr(
                                \ lines[-1].text,
                                \ '\s\+\zs\S\+\]\ze:$',
                               \ )
            if empty(functions)
                continue
            en
            let lines[-1].text = substitute(
                                        \ lines[-1].text,
                                        \ '\v\s+\S+:$',
                                        \ '',
                                        \ '',
                                     \ )
            for func_line in split(functions, '\.\.')
                call add(lines, {'text': func_line})
                let lnum = matchstr(
                                \ func_line,
                                \ '\[\zs\d\+\ze\]$',
                             \ )
                " 去掉lnum
                let function = substitute(
                                    \ func_line,
                                    \ '\[\d\+\]$',
                                    \ '',
                                    \ '',
                                   \ )
                if function =~# '[\\/.]' && s:file_readable(get(
                                                            \ virtual,
                                                            \ function,
                                                            \ function,
                                                           \ ))
                    let lines[-1].filename = get(virtual, function, function)
                    let lines[-1].lnum = lnum
                    let lines[-1].text = ''
                    continue

                elseif function =~# '^\d\+$'
                    let function = '{' . function . '}__leo__debug'
                en

                let list = &list
                try
                    set nolist
                    let output = split(
                                    \ scriptV#capture('verbose function '.function),
                                    \ "\n",
                                \ )
                finally
                    let &list = list
                endtry

                let filename = expand(matchstr(
                                        \ get(output, 1, ''),
                                        \ 'from \zs.*',
                                       \ )
                                \)
                let filename = substitute(filename, ' \S\+ \d\+$', '', '')
                let filename = get(virtual, filename, filename)
                if !s:file_readable(filename)
                    let lines[-1].text .= string(filename)
                    continue
                en
                let implementation = map(output[2:-2], 'v:val[len(matchstr(output[-1],"^ *")) : -1]')
                call map(implementation, 'v:val ==# " " ? "" : v:val')
                let body = []
                let offset = 0
                for line in s:read_file(filename)
                    if line =~# '^\s*\\' && !empty(body)
                        let body[-1][0] .= s:subs(line, '^\s*\\', '')
                        let offset += 1
                    el
                        call extend(body, [[s:subs_g(line, "\t", repeat(" ", &tabstop)), offset]])
                    en
                endfor
                for j in range(len(body)-len(implementation)-2)
                    if function =~# '^{'
                        let pattern = '.*\.'
                    elseif function =~# '^<SNR>'
                        let pattern = '\%(s:\|<SID>\)' . matchstr(function, '_\zs.*') . '\>'
                    el
                        let pattern = function . '\>'
                    en
                    if body[j][0] =~# '\C^\s*fu\%[nction]!\=\s*'.pattern
                                \ && (body[j + len(implementation) + 1][0] =~# '\C^\s*endf'
                                \ && map(body[j+1 : j+len(implementation)], 'v:val[0]') ==# implementation
                                \ || pattern !~# '\*')
                        let lines[-1].filename = filename
                        let lines[-1].lnum = j + body[j][1] + lnum + 1
                        let lines[-1].valid = 1
                        let found = 1
                        break
                    en
                endfor
            endfor
        endfor
        call setqflist(lines)
        if exists(':chistory')
            call setqflist([], 'r', {'title': ':Messages'})
        en
        copen
        $
        call search('^[^|]', 'bWc')
        return ''
    endf

" :Runtime
    func! s:unlet_them(files) abort
        let loadedS = []
        for file in a:files
            if s:file_readable(file)
                let lines = s:read_file(file, 500)  "\ 为什么是500, 100太少了?
                if len(lines)
                    for var_pos in range( len(lines)-1 )
                    " 逐行读取 找 类似: if exists('g:autoloaded_scriptV')   | finish  | en
                        let unlet_me = matchstr(
                                            \lines[var_pos],
                                            \'^\s*if .*\<exists *( *[''"]\%\(g:\)\=\zs[A-Za-z][0-9A-Za-z_#]*\ze[''"]',
                                          \)
                                                                "\ 单引号里的单引号, 要用''表示
                                                                      " g: global var
                                                                      " 无法处理¿s:¿var (只能在script内部处理?)
                                                                              "\ b:var呢?
                                                                "\ 形如 `autoloaded_scriptV` 这类标志变量
                        if unlet_me !=# ''
                        \&& index(loadedS, unlet_me) == -1
                            for finish_pos in range(0, 4)
                            " finish一般出现在4行之内?
                                let a_line = get(lines, var_pos + finish_pos, '')
                                if a_line   =~#   '\v(^|\|)\s*finish>'
                                    "\ 关键一步:
                                    call add( loadedS, unlet_me)
                                    break
                                en
                            endfor
                        en
                    endfor
                en
            en
        endfor

        if empty(loadedS)
            return ''
        el
            return 'unlet! ' . join( map(loadedS, '"g:" . v:val'), ' ' )
        en
    endf

    func! s:len_compare(a, b) abort
        return len(a:a) - len(a:b)
    endf

    func! scriptV#locate(path) abort
        " 好复杂,别管
        let path = fnamemodify(a:path, ':p')
        let candidates = []
        for glob in split(&runtimepath, ',')
            let candidates += filter(s:glob(glob), 'path[0 : len(v:val)-1] ==# v:val && path[len(v:val)] =~# "[\\/]"')
        endfor
        if empty(candidates)
            return ['', '']
        en
        let preferred = sort(candidates, s:function('s:len_compare'))[-1]
        return [preferred, path[strlen(preferred)+1 : -1]]
    endf

    func! scriptV#runTime(bang, ...) abort

        let unletS = []
        let do_ = []
        let predo = ''

        if ! a:0 " 传参时没传... .   形如 :Runtime[!] , 处理当前文件

            if      &filetype !=# 'vim'
            \ && expand('%:e') !=# 'vim'
            " 不是vim脚本,  只去掉include guard, 再:filetype detect

                " echom '后缀不是.vim.  modeline指定的filetype是: ' .. &filetype
                for _type in split(&filetype, '\.')
                                    " modeline里可以指定多种filetype:   vim: set filetype=type1.type2.type3
                                        " 但echo &syntax 是不会分开显示type1.type2.type3的, 似乎是识别为一串无法识别的字符
                                        " 基本不会遇到&filetype中有多个元素的情况
                                        " echom '断开后是' _type

                    " 消除这些script的作用
                    for pattern in [
                        \'ftplugin/%s.vim',
                        \'ftplugin/%s_*.vim',
                        \'ftplugin/%s/*.vim',
                        \
                        \'indent/%s.vim',
                        \
                        \'syntax/%s.vim',
                        \'syntax/%s/*.vim',
                        \]
                        let rt_file = printf(pattern, _type)
                                     " 把每个pattern的%s换成_type中的内容

                        " list吞并别的list
                        let unletS += split( s:globrtp(rt_file), "\n" )
                    endfor
                endfor

                let exe_str = s:unlet_them(unletS)

                " if expand('%:p') =~  '/home/wf/.local/share/nvim/plugged/*/doc/*.txt'
                " " if expand('%:p') ==  '/home/wf/.local/share/nvim/plugged/*/doc/*.txt'
                "     " 这2行一样?
                "
                "     " vim的插件的doc/.txt (help文件) :filetype detect后成了txt文件
                "     if exe_str !=# ''
                "         let exe_str .= ' | '
                "     endif
                "     let exe_str .= 'filetype detect'
                " endif

                if exe_str !=# ''
                    let exe_str .= ' | '
                en
                let exe_str .= 'filetype detect'

                return exe_str

            el  " 是vim脚本 ,准备执行:runtime
                let files = [scriptV#locate(expand('%:p'))[1]]
                            " 在'runtimepath'中查找文件?
                " echom '进了else    files是:'  files
                if empty(files[0])
                    let files = ['%']
                en

                if &modified && (&autowrite || &autowriteall)
                    let predo = 'silent wall | '
                en

            en

        el  " 形如 :Runtime[!] {file1} .... {fileN}
            let files = a:000
        en

        for file_name in files  " 我一般只涉及一个文件, 只for一次
                              " files里可能含 非.vim的文件
            "\ 这个if分支我基本没进入过
            if file_name =~# '\v^('
                            \ . '[%#~]'  . '|'
                            \ . '\.?[/\\]' . '|'
                            \ . '\a+:'    . '|'
                            \ . '\d+'
                          \ .')$'
                              "\   %表示 当前文件
                              "\   #表示 alternative file,
                              "\  :~表示 Reduce file name to be relative to the home directory?
                        "\           \a+:  g:var b:var s:var?
                                  " \d+ : buffer号?

               " 进入了这个分支, 说明不在'runtimepath'中? 所以作者用:source (而非:runtim)?
               " 现在这个分支啥也不干?
               " 但%(当前文件) 和#(alternative file) 可能在runtimepath啊

                    " echom '复杂正则匹配的"file_name"变量是: '  file_name  ', expand后是: '  expand(file_name .. ':p')
                let file_name = scriptV#scriptname(file_name)

                  " unletS一开始是空list       see  *wildcard*
                                              " 大括号表示{4}等指定匹配数的东西?
                let unletS +=   file_name =~# '[[*?{]'
                                        \ ?   s:glob(file_name)
                                        \ : [ expand(file_name) ]
                " 我扔了, 避免source 临时的vim脚本(真要source时, 自己敲ctrl-s 调用这里的filetype detect再:source)
                    " let do_ += map(
                    "     \copy(unletS),
                    "     \'"source ".escape(v:val, " \t|!")',
                       "\ "     "\ source了.txt .py等文件 会很麻烦?
                    "     \)
            el  " :runtime
                let unletS += split(s:globrtp(file_name), "\n")
                if get(do_, 0, [''])[0] !~#  '^runtime!'
                    let do_ += ['runtime!']
                en
                let do_[-1] .= ' ' . escape(file_name, " \t|!")
                "\ echom "do_[-1] 是: "   do_[-1]
            en
        endfor

        if empty(a:bang)  | call extend(do_, ['filetype detect'])  | en

        let exe_str = s:unlet_them(unletS)
        if exe_str !=# '' |  let exe_str .= ' | ' |  endif
        let exe_str .= join(do_, ' | ')
        "\ echom '执行了  :' predo . exe_str
        "\ 本函数已经可以unlet本文件 顶部的g:autoloaded_scriptV,
        " 为啥还是要退出sessin后 再进入vim 修改才生效?
        return predo . exe_str
    endf

" :Disarm
    func! scriptV#disarm_command(bang, ...) abort
        let files  = []
        let unletS = []
        for in_put in a:000
            if in_put =~# '^\.\=[\\/]\|^\a\+:\|^[%#~]\|^\d\+$'
                let in_put = expand(scriptV#scriptname(in_put))
                if s:isdirectory(in_put)
                    let in_put .= "/**/*.vim"
                en
                let files += s:glob(in_put)
            el
                let files += split(s:globrtp(in_put), "\n")
            en
        endfor

        for file in files
            let unletS += [ scriptV#disarm(expand(file)) ]
        endfor

        echo join(files, ' ')
        return join(
              \ filter(unletS, 'v:val !=# ""'),
              \ '|',
             \)
    endf


    func! scriptV#disarm(file) abort
        let augroups = filter(
                        \ s:read_file(a:file),
                        \ 'v:val =~# "\v^\\s*aug%[roup]\\s"',
                       \ )
        call filter(
             \ augroups,
             \ 'v:val !~# "\\v^\\s*aug%[roup]\\s+END"',
            \ )

        for augroup in augroups
            exe augroup
            "\ echom "augroup 是: "   augroup
            "\ augroup 是:      aug  scriptV
            au!
            aug  END
            exe s:subs(augroup, 'aug\%[roup]', '&!')
            "\ 形如:
            " exe aug scriptV
        endfor
        call s:disable_maps_and_commands(a:file, 0)
        let tabnr    = tabpagenr()
        let winnr    = winnr()
        let altwinnr = winnr('#')
        tabdo windo   call s:disable_maps_and_commands(a:file, 1)
        exe 'tabnext ' . tabnr
        exe altwinnr . 'wincmd w'
        exe winnr . 'wincmd w'
        return s:unlet_them([a:file])
    endf

    func! s:disable_maps_and_commands(file, buf) abort
        let last_set = "\tLast set from " . fnamemodify(a:file, ':~')
        for line in split(scriptV#capture('verbose command'), "\n")
            if line ==# last_set
                if last[2] ==# (a:buf ? 'b' : ' ')
                    exe 'delcommand '.matchstr(last[4:-1], '^\w\+')
                en
            el
                let last = line
            en
        endfor
        for line in split(scriptV#capture('verbose map').scriptV#capture('verbose map!'), "\n")
            if line ==# last_set
                let map = matchstr(last, '^.\s\+\zs\S\+')
                let rest = matchstr(last, '^.\s\+\S\+\s\+\zs[&* ][ @].*')
                if rest[1] ==# (a:buf ? '@' : ' ')
                    let cmd = last =~# '^!' ? 'unmap! ' : last[0].'unmap '
                    exe cmd.(a:buf ? '<buffer>' : '').map
                en
            el
                let last = line
            en
        endfor
    endf



" :Breakadd, :Breakdel
    func! s:breaksnr(arg) abort
        let id = scriptV#scriptid('%')
        if id
            return s:subs_g(a:arg, '^func.*\zs%(<s:|\<SID\>)', '<SNR>'.id.'_')
        el
            return a:arg
        en
    endf

    func! s:break(type, arg) abort
        if a:arg ==# 'here' || a:arg ==# ''
            let lnum = searchpair('^\s*fu\%[nction]\>.*(', '', '^\s*endf\%[unction]\>', 'Wbn')
            if lnum && lnum < line('.')
                let function = matchstr(getline(lnum), '^\s*\w\+!\=\s*\zs[^( ]*')
                if function =~# '^s:\|^<[Ss][Ii][Dd]>'
                    let id = scriptV#scriptid('%')
                    if id
                        let function = s:subs(function, '^s:|^\<[Ss][Ii][Dd]\>', '<SNR>'.id.'_')
                    el
                        return 'echoerr "Could not determine script id"'
                    en
                en
                if function =~# '\.'
                    return 'echoerr "Dictionary functions not supported"'
                en
                return 'break'.a:type.' func '.(line('.')==lnum ? '' : line('.')-lnum).' '.function
            el
                return 'break'.a:type.' here'
            en
        en
        return 'break'.a:type.' '.s:breaksnr(a:arg)
    endf

    func! s:Complete_breakadd(A, L, P) abort
        let functions = join(sort(map(split(scriptV#capture('function'), "\n"), 'matchstr(v:val, " \\zs[^(]*")')), "\n")
        if a:L =~# '^\w\+\s\+\w*$'
            return "here\nfile\nfunc"
        elseif a:L =~# '^\w\+\s\+func\s*\d*\s\+s:'
            let id = scriptV#scriptid('%')
            return s:subs_g(functions,'\<SNR\>'.id.'_', 's:')
        elseif a:L =~# '^\w\+\s\+func '
            return functions
        elseif a:L =~# '^\w\+\s\+file '
            return glob(a:A."*")
        el
            return ''
        en
    endf

    func! s:Complete_breakdel(A, L, P) abort
        let args = matchstr(a:L, '\s\zs\S.*')
        let list = split(scriptV#capture('breaklist'), "\n")
        call map(list, 's:subs(v:val, ''^\s*\d+\s*(\w+) (.*)  line (\d+)$'', ''\1 \3 \2'')')
        if a:L =~# '^\w\+\s\+\w*$'
            return "*\nhere\nfile\nfunc"
        elseif a:L =~# '^\w\+\s\+func\s'
            return join(map(filter(list, 'v:val =~# "^func"'), 'v:val[5 : -1]'), "\n")
        elseif a:L =~# '^\w\+\s\+file\s'
            return join(map(filter(list, 'v:val =~# "^file"'), 'v:val[5 : -1]'), "\n")
        el
            return ''
        en
    endf

" :Vopen, :Vedit, ...
    func! s:winnr_of_preview() abort
        for i in range(1, winnr('$'))
            if getwinvar(i, '&previewwindow') == 1
                return i
            en
        endfor
        return -1
    endf

    func! scriptV#edit_runtime_file(count, cmd, file, lcd01) abort
                        " count:
                            "  count_th matching file in 'runtimepath',
                        " 默认是1
        "\ 找到所以想要的script
            let file_re = substitute(a:file, '\.vim$', '', '') . '.vim'

            "\ 先在$nV等目录 (而非其子目录)找
                let foundS = split(
                              \ globpath(
                                      \ escape(&runtimepath, ' '),
                                      \ file_re
                                      \ ),
                              \ "\n"
                            \ )
                let found = get(
                         \ foundS,
                         \ a:count - 1,
                         \ '',
                        \ )

            if found ==# ''
                let foundS = []
                for sub_dir in ['autoload', 'syntax', 'ftplugin', 'indent', 'ftdetect']
                    let foundS +=  split(
                                    \ globpath(
                                            \ escape(&runtimepath, ' '),
                                            \ sub_dir . '/' . file_re,
                                            \ ),
                                    \ "\n",
                                 \ )
                endfor

                if len(foundS) == 0
                    return 'echom "autoload, syntax等里面都找不到"'
                el
                "\ foundS有些文件 的内容重复, 需要过滤:
                    let foundS_not_rt = [ foundS[0] ]  "\ not in $VIMRUNTIME

                    for i in range( 1, len(foundS) - 1 )
                        if  foundS[i]  !~  '/home/linuxbrew/.linuxbrew/Cellar/neovim'
                            call add(foundS_not_rt, foundS[i])

                        el  "\ 对于$RUNTIME里的文件f甲
                        "\ 只有当$nV或PL目录下 不存在相应的文件时,
                            "\ 才包含f甲
                            if foundS[i-1] =~ '/after/'
                                "\ $RUNTIME里的文件不会和/after/下的重合
                                call add(foundS_not_rt, foundS[i])
                            el

                                if  foundS[i] !~  join(  split(foundS[i-1], '/')[-2:-1],    '/' )
                                    call add(foundS_not_rt, foundS[i])
                                en
                            en
                        en
                    endfor

                    let found = get(
                              \ foundS_not_rt,
                              \ a:count - 1,
                              \ '',
                             \ )
                en

            en

        "\ 决定用如何处理找到的script (:edit/tabedit...)
            if a:cmd ==# 'read'
                return a:cmd . ' ' . s:fnameescape(found)

            elseif a:lcd01
                let path = found[0: -strlen(file_re) - 2 ]
                                            " -2: 扔掉.vim?
                                            " 扔掉search的内容?
                return a:cmd . '.s:fnameescape(found) . '| lcd ' . s:fnameescape(path)

            el  " V¿xxxx¿的a:cmd大部分是¿xxxx¿
                let window  = 0
                let precmd  = ''
                let postcmd = ''

                if a:cmd =~# '^pedit'
                    try
                        exe 'silent ' . a:cmd
                    catch   /^Vim\%((\a\+)\)\=:E32/
                    endtry

                    let window = s:winnr_of_preview()  " 获取previewwindow的winnr
                    let precmd = printf( '%d wincmd w |' ,   window)
                                        " wincmd: Like executing ctrl-w [count] {arg}.
                    let postcmd = '| wincmd w'

                elseif a:cmd !~# '^edit'
                    exe a:cmd
                        " split等
                en

                if !exists('foundS_not_rt') || len(foundS_not_rt) == 1
                    return '-tab edit' . found

                el "\   len  > 1
                    "\ call setloclist(0, map...  简单试了下, 失败
                    call setqflist(
                            \ map(
                                \ foundS_not_rt                     ,
                                \ '{
                                    \ "filename" : v:val   ,
                                    \ "text"     : ""      ,
                                    \ "valid"    : 1
                                \ }'                         ,
                            \ )
                        \)
                    call setqflist([], 'a', {'title' : '...'})

                    return precmd
                        \ .    'cc' . matchstr(a:cmd, '!$') . ' ' . a:count
                        \ . ' | copen ' . len(foundS_not_rt)
                        \ .  '| let b:scriptS_cmd = "' . a:cmd . '"'
                        \ . postcmd
                                      " matchstr
                                        " When there is no match:
                                         "     ¿""¿ is returned.
                                      " 得到   ¿cc¿ 或者 ¿cc!¿
                en
            en
    endf


" :Time
    func! scriptV#time_command(cmd, count) abort
        let time = reltime()
        try
            if a:count > 1
                let i = 0
                while i < a:count
                    exe     a:cmd
                    let i += 1
                endwhile
            el
                exe     a:cmd
            en
        finally
            let elapsed = reltime(time)
            redraw
            echomsg matchstr(reltimestr(elapsed), '.*\..\{,3\}') . ' seconds to run :'.a:cmd
        endtry
        return ''
    endf

nno zS  :<C-U>exe scriptV#synnames_map(v:count)<CR>
    func! scriptV#synnames(...) abort
        if a:0
            let [line, col] = [a:1, a:2]
        el
            let [line, col] = [line('.'), col('.')]
        en
        return reverse(  map(
                      \ synstack(line, col)       ,
                      \ 'synIDattr(v:val,  "name")' ,
                     \ )
                \)
    endf
    func! scriptV#synnames_map(count) abort
        if a:count
            let name = get(
                          \ scriptV#synnames(),
                          \ a:count-1,
                          \ '',
                         \ )
            if name !=# ''  | return 'syntax list '.name  | en
        el
            echo join(scriptV#synnames(), ' ')
        en
        return ''
    endf



func! scriptV#smart_help() abort
    "\ Like setting 'keywordprg' to :help,
    "\ but slightly  smarter.
    "\ Only mapped in Vim files.

    "\ 在下面用到了

    let col = col('.') - 1
    while   col && getline('.')[col] =~# '\k'
        let col -= 1
    endwhile

    let pre = col == 0
                \ ? ''
                \ : getline('.')[0 : col]

    "\ -----

    let col = col('.') - 1
    while   col && getline('.')[col] =~# '\k'
        let col += 1
    endwhile

    let post = getline('.')[col : -1]

    let syn_name = get(scriptV#synnames(), 0, '')
    let cword = expand('<cword>')
    if &syntax == 'vim'
        if syn_name ==# 'vimFuncName'
            return  cword . '()'

        elseif syn_name ==# 'vimOption'
            return  "'" . cword . "'"

        elseif syn_name ==# 'vimUserAttrbKey'
            return  ':command-' . cword

        elseif pre =~#   '^\s*:\=$'
            return  ':' . cword

        elseif pre =~#  '\<v:$'
            return  'v:' . cword

        elseif cword ==# 'v'
        \ && post =~# ':\w\+'
            return  'v' . matchstr(post, ':\w\+')
        el
            return  cword
        en
    el
    "\ syntax == 'help'
        if syn_name ==# 'In_Single_quotE'
            return  "'" . cword . "'"
        el
            return cword
        en
endf

" setup  可以放到autoload/vim.vim和help.vim?
    func! scriptV#setup_help() abort
        let &l:path = s:build_path()
        com!  -bar -bang -buffer Console PP

        "\ nno  <buffer>  gh
        nno            gh
                          \  <Cmd>silent! helptags ALL<cr>
                            \<Cmd>let @h = scriptV#smart_help()<cr>
                            \:<C-U>-tab help <C-R>h


    endf


    func! scriptV#setup_vim() abort
        let &l:path = s:build_path()
        setl     suffixesadd=.vim    keywordprg=:help
        setl     includeexpr=scriptV#includeexpr(v:fname)
        setl     include=^\\s*\\%(so\\%[urce]\\\|ru\\%[ntime]\\)[!\ ]\ *\\zs[^\\|]*
        setl     define=^\\s*fu\\%[nction][!\ ]\\s*\\%(s:\\)\\=

        cno  <expr><buffer>   <Plug><cfile> scriptV#cfile()

        let runtime = scriptV#locate(expand('%:p'))[1]
        let b:dispatch =   ':Runtime ' . s:fnameescape( len(runtime)
                                                \ ? runtime
                                                \ : expand('%:p')
                                            \ )

        com!     -bar -bang -buffer
            \ Console
            \ Runtime | PP

        com!     -buffer -bar -nargs=? -complete=custom,s:Complete_breakadd
            \ Breakadd
            \ :exe s:break('add',<q-args>)

        com!     -buffer -bar -nargs=? -complete=custom,s:Complete_breakdel
            \ Breakdel
            \ :exe s:break('del',<q-args>)


        nno  <buffer>  gh
                         \  <Cmd>silent! helptags ALL<cr>
                           \<Cmd>let @h = scriptV#smart_help()<cr>
                           \:<C-U>-tab help <C-R>h

        let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') ..
            \ '|setl   path= suffixesadd= includeexpr= include= define= keywordprg='
          \ . '|sil!   delcommand Breakadd'
          \ . '|sil!   delcommand Breakdel'
          \ . '|sil!   exe "nunmap <buffer> <c-k>"'
    endf


        func! s:build_path() abort
            let old_path = substitute(&g:path, '\v^\.,/%(usr|emx)/include,,,?', '', '')
            let new_path = escape(&runtimepath, ' ')
            return !empty(old_path) ? old_path.','.new_path
                                 \: new_path
        endf

        func! scriptV#includeexpr(file) abort
            if a:file =~# '^\.\=[A-Za-z_]\w*\%(#\w\+\)\+$'
                let f = substitute(a:file, '^\.', '', '')
                return 'autoload/'.tr(matchstr(f, '[^.]\+\ze#') . '.vim', '#', '/')
            en
            return substitute(a:file, '\m\C<sfile>\(\%(:\w\)*\)', '\=expand("%:p".submatch(1))', 'g')
        endf

        func! scriptV#cfile() abort
            if matchend(getline('.'), &include) >= col('.')
                let cfile = matchstr(getline('.'), &include)
            el
                let cfile = expand('<cfile>')
            en
            if empty(cfile)
                return "\<C-R>\<C-F>"
            elseif cfile =~# '^\.\=[A-Za-z_]\w*\%(#\w\+\)\+$'
                return '+djump\ ' . matchstr(cfile, '[^.]*') . ' ' . s:fnameescape(scriptV#includeexpr(cfile))
            el
                return s:fnameescape(scriptV#includeexpr(cfile))
            en
        endf

